<?php

namespace Xin\LaravelFortify\Foundation\Middleware;

use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Cookie\CookieJar;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class CheckForSafeVisit
{

    use InteractsExcept;

    /**
     * @var Application
     */
    protected $app;

    /**
     * @var Repository
     */
    protected $config;

    /**
     * @var array
     */
    protected $except = [];

    /**
     * CheckForSafeVisit constructor.
     *
     * @param Application $app
     */
    public function __construct(Application $app)
    {
        $this->app = $app;
        $this->config = $app['config'];
    }

    /**
     * 检查站点是否允许访问
     *
     * @param Request $request
     * @param \Closure $next
     * @return mixed
     * @throws \Exception
     */
    public function handle(Request $request, \Closure $next)
    {
        $safeKey = $this->localSafeKey($request);

        $path = $request->modulePath();
        if ($safeKey == $path) {
            /** @var CookieJar $cookieJar */
            $cookieJar = $this->app['cookie'];
            $cookie = $cookieJar->forever($this->cookieSafeKeyName(), $safeKey);
            $cookieJar->queue($cookie);

            throw new HttpResponseException(new Response("safed visit!", 200));
        } elseif ($safeKey != $this->clientSafeKey($request)) {
            // 要排除的URL
            if ($this->isExcept($request)) {
                return $next($request);
            }

            throw new HttpResponseException(new Response("404 Not Found: Not Safed Visit.", 404));
        }

        return $next($request);
    }

    /**
     * 获取本地的[safe_key]
     *
     * @param Request $request
     * @return string
     */
    protected function localSafeKey(Request $request)
    {
        return $this->config->get('app.safe_key');
    }

    /**
     * 获取 cookie 存储的[safe_key]名称
     *
     * @return string
     */
    protected function cookieSafeKeyName()
    {
        return '__safe_key__';
    }

    /**
     * 获取当前请求的[safe_key]
     *
     * @param Request $request
     * @return string
     */
    protected function clientSafeKey(Request $request)
    {
        if ($localSafeKey = $request->header($this->headerSafeKeyName())) {
            return $localSafeKey;
        }

        return $request->cookie($this->cookieSafeKeyName());
    }

    /**
     * 获取 header 传递的 [safe_key]名称
     * @return string
     */
    protected function headerSafeKeyName()
    {
        return "Safe-Key";
    }

}
